package com.xcm.sso.client.filter;


import com.xcm.sso.client.config.CustomProperties;
import com.xcm.sso.client.constant.SSOFilterConstant;
import com.xcm.sso.client.util.RestClientUtils;
import org.json.JSONException;
import org.json.JSONObject;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;

import javax.servlet.*;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

/**
 * 登录验证filter
 */
public class SSOLoginFilter implements Filter {
	private String cookieName;
	private String ssoServerUrl;
	private String platformTag;

	@Override
	public void init(FilterConfig filterConfig) throws ServletException {
		ServletContext servletContext = filterConfig.getServletContext();
		WebApplicationContext webApplicationContext = WebApplicationContextUtils.getWebApplicationContext(servletContext);
		CustomProperties customProperties = (CustomProperties) webApplicationContext.getBean("customProperties");
		cookieName = customProperties.getCookieName();
		ssoServerUrl = customProperties.getSsoLoginUrl();
		platformTag = customProperties.getPlatformTag();
	}

	@Override
	public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException {
		HttpServletRequest request = (HttpServletRequest)req;
		HttpServletResponse response = (HttpServletResponse)resp;
		//上下文路径
		String path = request.getContextPath();

		String gotoURL = request.getParameter(SSOFilterConstant.SSO_FILTER_GOTOURL);
		if (gotoURL == null) {
			gotoURL = request.getRequestURL().toString();
		}
		StringBuilder urlSb = new StringBuilder(ssoServerUrl);
		urlSb.append("preLogin?setCookieURL=").append(request.getScheme()).append("://")
				.append(request.getServerName()).append(":").append(request.getServerPort())
				.append(path).append("/setCookie&gotoURL=").append(gotoURL).append("&platformTag=").append(platformTag);
		String url = urlSb.toString();

		Cookie ticket = null;
		Cookie[] cookies = request.getCookies();
		if (cookies != null) {
			for (Cookie cookie : cookies) {
				if (cookie.getName().equals(cookieName)) {
					ticket = cookie;
					break;
				}
			}
		}
		if (request.getRequestURI().equals(path + "/logout")) {
			doLogout(request, response, ticket, path, gotoURL);
		} else if (request.getRequestURI().equals(path + "/setCookie")) {
			setCookie(request, response);
		} else if (ticket != null) {
			authCookie(request, response, chain, ticket, path, gotoURL);
		} else {
			response.sendRedirect(url);
		}
		return;
	}

	/**
	 * 验证Cookie
	 */
	private void authCookie(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Cookie ticket, String path, String gotoURL) throws ServletException, IOException {
		Map<String, Object> params = new HashMap<>();
		params.put(SSOFilterConstant.SSO_FILTER_COOKIENAME, ticket.getValue());
		StringBuilder urlSb = new StringBuilder(ssoServerUrl);
		urlSb.append("authTicket?setCookieURL=").append(request.getScheme()).append("://")
				.append(request.getServerName()).append(":").append(request.getServerPort())
				.append(path).append("/setCookie&gotoURL=").append(gotoURL);
		String url = urlSb.toString();
		try {
			JSONObject result = post(url, params);
			int code = result.getInt("code");
			if (SSOFilterConstant.CODE_SUCCESS == code) {
				// TODO: 2018/4/28  处理用户信息 request.setAttribute("username", result.getString("username"));
				chain.doFilter(request, response);
				return;
			} else {
				urlSb.setLength(0);
				urlSb.append(ssoServerUrl);
				urlSb.append("preLogin?setCookieURL=").append(request.getScheme()).append("://")
						.append(request.getServerName()).append(":").append(request.getServerPort())
						.append(path).append("/setCookie&gotoURL=").append(gotoURL);
				response.sendRedirect(urlSb.toString());
				return;
			}
		} catch (JSONException e) {
			e.printStackTrace();
		}
	}

	/**
	 * 设置Cookie
	 */
	private void setCookie(HttpServletRequest request, HttpServletResponse response) throws IOException {
		Cookie ticket = new Cookie(cookieName, request.getParameter(SSOFilterConstant.SSO_FILTER_TICKET));
		ticket.setPath("/");
		ticket.setMaxAge(Integer.parseInt(request.getParameter(SSOFilterConstant.SSO_FILTER_EXPIRY)));
		response.addCookie(ticket);

		String gotoURL = request.getParameter(SSOFilterConstant.SSO_FILTER_GOTOURL);
		if (gotoURL != null) {
			response.sendRedirect(gotoURL);
		}
	}

	/**
	 * 注销
	 */
	private void doLogout(HttpServletRequest request, HttpServletResponse response, Cookie ticket, String path, String gotoURL) throws IOException {
		Map<String, Object> params = new HashMap<>();
		params.put(SSOFilterConstant.SSO_FILTER_COOKIENAME, ticket.getValue());
		StringBuilder urlSb = new StringBuilder(ssoServerUrl);
		urlSb.append("logout?setCookieURL=").append(request.getScheme()).append("://")
				.append(request.getServerName()).append(":").append(request.getServerPort())
				.append(path).append("/setCookie&gotoURL=").append(gotoURL);
		String url = urlSb.toString();
		try {
			JSONObject result = post(url, params);
			int code = result.getInt("code");
			//注销成功
			if (SSOFilterConstant.CODE_SUCCESS == code) {
				ticket.setValue("");
			}
		} catch (JSONException e) {
			throw new RuntimeException(e);
		}
	}

	private JSONObject post(String url, Map<String, Object> params) throws IOException, JSONException {
		String post = RestClientUtils.post(url, params, "UTF-8");
		return new JSONObject(post);
	}

	@Override
	public void destroy() {

	}
}
